﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AIthin.Neuro
{
    /// <summary>
    /// EmbryoNeuron is embryo that will be a neuron
    /// </summary>
    [Serializable]
    public class EmbryoNeuron // : INeuron
    {
       int ActivityCountToBorn { get; set; }
        /// <summary>
        /// wieviel inputs zu allen inputs sollen gleich sein um änlichkeit
        /// mit neuron festzustellen
        /// </summary>
        static float ActivInputsRate { get; set; }
        static int InputsCount { get; set; }
        public int WasActiv { get; set; }
        static float ActivityRadius;
        public int LifeTime { get; protected set; }
        public float X { get; protected set; }
        public float Y { get; protected set; }
        public float Z { get; protected set; }
        /// <summary>
        /// ident number
        /// </summary>
        public int ID { get; protected set; }
        /// <summary>
        /// is embryo activated
        /// </summary>
        public bool Activated { get; protected set; }
        /// <summary>
        /// array of neurons IDs that can be connected  
        /// </summary>
        public int[] Connections { get; protected set; }
        /// <summary>
        /// is embryo ready to born or not
        /// </summary>
        public bool ReadyToBorn { get; protected set; } 
        public bool wasBorn { get; set; }
        /// <summary>
        /// get first embryo and remove active neurons from list
        /// </summary>
        /// <param name="NeuronsToConnect">List of active neurons</param>
        public EmbryoNeuron(ref List<int> NeuronsToConnect)
        {
            WasActiv = 0;
            ActivityRadius = 3.0f;
            ActivityCountToBorn = 50;
            ActivInputsRate = 0.7f;
            InputsCount = 6;
            Connections = new int[Math.Min(InputsCount, NeuronsToConnect.Count)];
            int StartNeuron = NeuronsToConnect[0];
            Connections[0] = StartNeuron;
            NeuronsToConnect.Remove(StartNeuron);
            Debug.WriteLine(Connections.Length, " new embryo, connections count");

            for (int i = 1; i < Connections.Length; i++)
            {
                //RES speed optimize
                Connections[i] = NeuronsToConnect[0];
                Debug.WriteLine(Connections[i], " connected to neuron");
                //remove connected neuron from list
                NeuronsToConnect.Remove(Connections[i]);
            }
            ReadyToBorn = false;
            wasBorn = false;
        }
        /// <summary>
        /// test if that embryo consist active neurons or not 
        /// </summary>
        /// <param name="NeuronsToConnect">list of neurons to connect</param>
        /// <returns>true when this embryo contanes (min 70%) of active neurons, else return false</returns>
        public bool IsIn(List<int> NeuronsToConnect)
        {
            LifeTime++;
            int IntersectionCount = 0;
            foreach (int i in Connections)
                if (NeuronsToConnect.Contains(i)) IntersectionCount++;
            // 70% embryo input is in
            if ((float)IntersectionCount / (float)Connections.Length > ActivInputsRate)
                return true;
           else
               return false;
        }
        /// <summary>
        /// change WasActiv variable and if was often activ set ReadyToBorn as true.
        /// </summary>
        public void Grow()
        {
            if (++WasActiv > ActivityCountToBorn) ReadyToBorn = true;
            return;
        }
        public void checkGrow()
        {
            if (WasActiv > ActivityCountToBorn) ReadyToBorn = true;
            return;
        }
        /// <summary>
        /// remove active neurons from list when embryo born
        /// </summary>
        /// <param name="ActiveNeurons">list of active neurons</param>
        public void RemoveFrom(ref List<int> ActiveNeurons)
        {
            foreach (int i in Connections)
                if(ActiveNeurons.Contains(i))
                    ActiveNeurons.Remove(i);
        }
    }
}
